/*!
 * \file te_header.c
 *
 * \brief 消息头操作
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.
 *
 * \version 1.0
 * \author songbb
 * \date 2016/09/24
 *
 */

#include <stdio.h>

#include "frct_comm.h"
#include "frct_detect_hash.h"

#include "te_comm.h"
#include "te_header.h"
#include "config.h"

int te_header_is_heartbeat(char *p_payload
                        , unsigned int ui_payload_len)
{
    if (ui_payload_len != 44)
        return FR_NO;

    if (memcmp(p_payload, "\x00\x00\x00\x00\x0e\x00", 6) != 0)
        return FR_NO;

    if (memcmp(p_payload + 6, "\x2c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3a\x00\x00\x00", 38) == 0 ||
        memcmp(p_payload + 6, "\x2c\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3b\x00\x00\x00", 38) == 0)
        return FR_YES;

    return FR_NO;
}

int te_header_detect(Conntrack *p_st_conn
                    , char *p_payload
                    , unsigned int ui_payload_len)
{
    TE_PRINT_INFO("te_header_detect...\n");
    TE_detect_session *p_st_detect_sess = NULL;

    if (ui_payload_len < APM_TE_HDR_LEN)
    {
        if (te_header_is_heartbeat(p_payload, ui_payload_len) == FR_YES)
        {
            if ((p_st_detect_sess = (TE_detect_session *) frct_detect_data_get(p_st_conn, MODULE_L7PROTO)) == NULL)
            {
                if ((p_st_detect_sess = (TE_detect_session *) frmalloc(sizeof(TE_detect_session))) == NULL)
                {
                    TE_MALLOCK_ERR;
                    goto unknown;
                }
                p_st_detect_sess->c_detect_succ_count = 0;

                if (frct_detect_hash_add(p_st_conn, MODULE_L7PROTO, (void *) p_st_detect_sess) != FR_SUCC)
                {
                    te_free((void **) &p_st_detect_sess);
                    goto unknown;
                }
            }

            p_st_detect_sess->c_detect_succ_count++;

            if (p_st_detect_sess->c_detect_succ_count >= APM_TE_DETECT_MAX)
                return APM_L7_IS_YES;
            else
                return APM_L7_IS_UNKNOWN;
        }

        goto unknown;
    }

    // 校验头6个字节是否为 0xcf0700000a6f
    if (memcmp(p_payload, "\xcf\x07\x00\x00\x0a\x6f", 6) != 0)
        goto unknown;

    PRINT_HEX_STRING("MAGIC", p_payload, 6);

    /*
     * 校验数据包类型
     * 5Z0200 – 用户同步/异步请求包
     * 5Z0210 – 用户同步/异步应答包
     * 5Z0202 – 用户同步/异步提交包
     * 5Z0212 - 用户同步/异步提交应答包
     * 5Z0402 – 用户同步/异步回滚包
     * 5Z0412 – 用户同步/异步回滚应答包
     * 5C0200 – 用户会话交易传输请求包
     * 5C0202 – 用户会话交易传输响应包
     * 5C0800 - 用户会话交易建立连接请求包
     * 5C0810 - 用户会话交易建立连接应答包
     * 5C0402 - 用户会话交易拆除连接通知包
     */
    if (memcmp(p_payload + 44, "\x35\x5A\x30\x32\x30\x30", 6) != 0 &&
        memcmp(p_payload + 44, "\x35\x5A\x30\x32\x31\x30", 6) != 0 &&
        memcmp(p_payload + 44, "\x35\x5A\x30\x32\x30\x32", 6) != 0 &&
        memcmp(p_payload + 44, "\x35\x5A\x30\x32\x31\x32", 6) != 0 &&
        memcmp(p_payload + 44, "\x35\x5A\x30\x34\x30\x32", 6) != 0 &&
        memcmp(p_payload + 44, "\x35\x5A\x30\x34\x31\x32", 6) != 0 &&
        memcmp(p_payload + 44, "\x35\x43\x30\x32\x30\x30", 6) != 0 &&
        memcmp(p_payload + 44, "\x35\x43\x30\x32\x30\x32", 6) != 0 &&
        memcmp(p_payload + 44, "\x35\x43\x30\x38\x30\x30", 6) != 0 &&
        memcmp(p_payload + 44, "\x35\x43\x30\x38\x31\x30", 6) != 0 &&
        memcmp(p_payload + 44, "\x35\x43\x30\x34\x30\x32", 6) != 0)
        goto unknown;

    // 校验 '|' 符号
    if (memcmp(p_payload + 50, "\x7c", 1) != 0 &&
        memcmp(p_payload + 59, "\x7c", 1) != 0 &&
        memcmp(p_payload + 68, "\x7c", 1) != 0)
        goto unknown;

    PRINT_HEX_STRING("TE Packet Type", p_payload + 44, 6);

    return APM_L7_IS_YES;
unknown:
    return APM_L7_IS_UNKNOWN;
}

int te_header_unpack(char *p_payload
                   , unsigned int ui_payload_len
                   , TE_header *p_st_te_header)
{
    char arr_ptxflag[9] = {'\0'};
    char arr_branchflag[9] = {'\0'};
    char arr_tid[7] = {'\0'};
    char arr_subtid[5] = {'\0'};
    char arr_ret_code[3] = {'\0'};
    char arr_user_data_len[5] = {'\0'};
    char arr_filename_len[5] = {'\0'};
    char arr_key_data_len[5] = {'\0'};
    char *p_ptxflag = NULL;
    char *p_branchflag = NULL;
    int i_ptxflag_len = 0;
    int i_branchflag_len = 0;
    int i_loop = 0;
    int i_hdr_len = 0;

    if (ui_payload_len < APM_TE_HDR_LEN)
        goto error;

    // 校验头6个字节是否为 0xcf0700000a6f
    if (memcmp(p_payload, "\xcf\x07\x00\x00\x0a\x6f", 6) != 0)
        goto error;

    if (memcmp(p_payload + 44, "\x35\x5A\x30\x32\x30\x30", 6) == 0)
    {
        p_st_te_header->pkt_type = TE_PKT_TYPE_SYNC_ASYNC_REQ;
        i_hdr_len = APM_TE_HDR_LEN;
    }
    else if (memcmp(p_payload + 44, "\x35\x5A\x30\x32\x31\x30", 6) == 0)
    {
        p_st_te_header->pkt_type = TE_PKT_TYPE_SYNC_ASYNC_RESP;
        i_hdr_len = APM_TE_HDR_LEN;
    }
    else if (memcmp(p_payload + 44, "\x35\x5A\x30\x32\x30\x32", 6) == 0)
    {
        p_st_te_header->pkt_type = TE_PKT_TYPE_SYNC_ASYNC_COMMIT_REQ;
        i_hdr_len = APM_TE_HDR_LEN;
    }
    else if (memcmp(p_payload + 44, "\x35\x5A\x30\x32\x31\x32", 6) == 0)
    {
        p_st_te_header->pkt_type = TE_PKT_TYPE_SYNC_ASYNC_COMMIT_RESP;
        i_hdr_len = APM_TE_HDR_LEN;
    }
    else if (memcmp(p_payload + 44, "\x35\x5A\x30\x34\x30\x32", 6) == 0)
    {
        p_st_te_header->pkt_type = TE_PKT_TYPE_SYNC_ASYNC_ABORT_REQ;
        i_hdr_len = APM_TE_HDR_LEN;
    }
    else if (memcmp(p_payload + 44, "\x35\x5A\x30\x34\x31\x32", 6) == 0)
    {
        p_st_te_header->pkt_type = TE_PKT_TYPE_SYNC_ASYNC_ABORT_RESP;
        i_hdr_len = APM_TE_HDR_LEN;
    }
    else if (memcmp(p_payload + 44, "\x35\x43\x30\x32\x30\x30", 6) == 0)
    {
        p_st_te_header->pkt_type = TE_PKT_TYPE_CVS_REQ;
        i_hdr_len = APM_TE_CVS_HDR_LEN;
    }
    else if (memcmp(p_payload + 44, "\x35\x43\x30\x32\x30\x32", 6) == 0)
    {
        p_st_te_header->pkt_type = TE_PKT_TYPE_CVS_RESP;
        i_hdr_len = APM_TE_CVS_HDR_LEN;
    }
    else if (memcmp(p_payload + 44, "\x35\x43\x30\x38\x30\x30", 6) == 0)
    {
        p_st_te_header->pkt_type = TE_PKT_TYPE_CVS_CONN_REQ;
        i_hdr_len = APM_TE_CVS_HDR_LEN;
    }
    else if (memcmp(p_payload + 44, "\x35\x43\x30\x38\x31\x30", 6) == 0)
    {
        p_st_te_header->pkt_type = TE_PKT_TYPE_CVS_CONN_RESP;
        i_hdr_len = APM_TE_CVS_HDR_LEN;
    }
    else if (memcmp(p_payload + 44, "\x35\x43\x30\x34\x30\x32", 6) == 0)
    {
        p_st_te_header->pkt_type = TE_PKT_TYPE_CVS_DISCONN;
        i_hdr_len = APM_TE_CVS_HDR_LEN;
    }
    else
        goto error;

    // PTxFlag
    memcpy(arr_ptxflag, p_payload + 51, 8);
    if (te_hex_string_to_bin(arr_ptxflag, &p_ptxflag, &i_ptxflag_len) != FR_SUCC)
        goto error;
    for (i_loop = 0; i_loop < i_ptxflag_len; i_loop++)
        p_st_te_header->i_ptxflag += p_ptxflag[i_loop] << (8 * (i_ptxflag_len - i_loop - 1));

    // BranchFlag
    memcpy(arr_branchflag, p_payload + 60, 8);
    if (te_hex_string_to_bin(arr_branchflag, &p_branchflag, &i_branchflag_len) != FR_SUCC)
        goto error;
    for (i_loop = 0; i_loop < i_branchflag_len; i_loop++)
        p_st_te_header->i_branchflag += p_branchflag[i_loop] << (8 * (i_branchflag_len - i_loop - 1));

    // 发起节点名
    memcpy(p_st_te_header->arr_original_node, p_payload + 69, 12);
    frtrim(p_st_te_header->arr_original_node);

    // 发送节点名
    memcpy(p_st_te_header->arr_send_node, p_payload + 81, 12);
    frtrim(p_st_te_header->arr_send_node);

    // 接收节点名
    memcpy(p_st_te_header->arr_recv_node, p_payload + 93, 12);
    frtrim(p_st_te_header->arr_recv_node);

    // 事务序号
    memcpy(arr_tid, p_payload + 105, 6);
    p_st_te_header->i_tid = atoi(arr_tid);

    // 事务分支序号
    memcpy(arr_subtid, p_payload + 111, 4);
    p_st_te_header->i_subtid = atoi(arr_subtid);

    // 服务名
    memcpy(p_st_te_header->arr_svcname, p_payload + 143, 20);
    frtrim(p_st_te_header->arr_svcname);

    // 响应码
    memcpy(arr_ret_code, p_payload + 163, 2);
    p_st_te_header->s_ret_code = (short) atoi(arr_ret_code);

    // 用户数据长度
    memcpy(arr_user_data_len, p_payload + 165, 4);
    p_st_te_header->i_user_data_len = atoi(arr_user_data_len);

    // 文件名长度
    memcpy(arr_filename_len, p_payload + 169, 4);
    p_st_te_header->i_filename_len = atoi(arr_filename_len);

    // 关键数据长度
    memcpy(arr_key_data_len, p_payload + 173, 4);
    p_st_te_header->i_key_data_len = atoi(arr_key_data_len);

    p_st_te_header->ui_header_len = (unsigned) i_hdr_len;
    p_st_te_header->ui_pkt_len = (unsigned) (i_hdr_len + p_st_te_header->i_user_data_len + p_st_te_header->i_filename_len + p_st_te_header->i_key_data_len);

    TE_PRINT_DBG("HdrLen:[%u]\n", p_st_te_header->ui_header_len);
    TE_PRINT_DBG("PktLen:[%u]\n", p_st_te_header->ui_pkt_len);
    TE_PRINT_DBG("常用包类型:[%s][%s]\n", TE_PKT_TYPE2STR(p_st_te_header->pkt_type), TE_PKT_TYPE2CNSTR(p_st_te_header->pkt_type));
    TE_PRINT_DBG("PTxFlag:[0x%08x]\n", p_st_te_header->i_ptxflag);
    TE_PRINT_DBG("BranchFlag:[0x%08x]\n", p_st_te_header->i_branchflag);
    TE_PRINT_DBG("发起节点名:[%s]\n", p_st_te_header->arr_original_node);
    TE_PRINT_DBG("发送节点名:[%s]\n", p_st_te_header->arr_send_node);
    TE_PRINT_DBG("接收节点名:[%s]\n", p_st_te_header->arr_recv_node);
    TE_PRINT_DBG("tid:[%d]\n", p_st_te_header->i_tid);
    TE_PRINT_DBG("subtid:[%d]\n", p_st_te_header->i_subtid);
    TE_PRINT_DBG("svcname:[%s]\n", p_st_te_header->arr_svcname);
    TE_PRINT_DBG("retCode:[%d]\n", p_st_te_header->s_ret_code);
    TE_PRINT_DBG("userDataLen:[%d]\n", p_st_te_header->i_user_data_len);
    TE_PRINT_DBG("filenameLen:[%d]\n", p_st_te_header->i_filename_len);
    TE_PRINT_DBG("keyDataLen:[%d]\n", p_st_te_header->i_key_data_len);

    te_free((void **) &p_ptxflag);
    te_free((void **) &p_branchflag);
    return FR_SUCC;
error:
    te_free((void **) &p_ptxflag);
    te_free((void **) &p_branchflag);
    return FR_FAIL;
}
